package com.yvon.maple.utils;


import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * rsa工具
 *
 * @author : Yvon
 * @since : 2021-11-10
 */
public class RsaUtils {
    /**
     * 私钥
     */
    public static String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAN0HbDLMyniG01oxmuPbO4yuFoGDyTWVpY2VX7ljgY1uoAyWR9zNFEAYhkHnRXfE11S/Fq9CNUkzAYtV8885ou6xFPCNveHxem6HXYJy+oTFAtOcYjkIZ7TnrfEGdRX6SYyS7orAVOlqoUQZ70LzIX+Pb2/TZNcPF8f/xlzF5z9TAgEDAoGAJNaSCHd3FBZ4jwhEe080l3JZFZX23kObl5jlSZCVl5JwAhkL+iIuCq7BCvvg6Ut5OMqDx+BeNt3Vlzj9997wfM4und2rbarl/CmkByguxVkbPYVVrnv3nONVDAu6yxe99pOMPFhg7LsFlLbYi6rrEoMJGn+IUhUZ8/oMc1vp4WsCQQD1nHHvU49Cbr1g6sQ19LaoA67mfnxjAt6d9dxm/I1/pBJYVTXGTW6pgrVJ81wtiQm6sKQANYhIOvG1fL6VpXSTAkEA5mDLbGXArafILJqTS+0uBluzleGlvZco9bnMWRfF7DGyxU/q58HuXv0ShuigxBYGwogs1f1iSEEebf7qCMaCQQJBAKO9oUo3tNb0fkCcgs6jJHACdJmpqEIB6b6j6ESoXlUYDDrjeS7eScZXI4aiPXOwsScgbVV5BYV8oSOofw5uTbcCQQCZldzy7oBzxTAdvGIynh6u580Olm5+ZMX5Jog7ZS6ddncuNUdFK/Q/U2GvRcCCuVnXBXM5U5ba1hRJVJwF2awrAkEAzpy/cxBn/vvha66KfpJgWFUjQ3+8IiVbZTUGiknAxOwRM5uRw4oOefTkfPv1D02ErOmZQO2nX8yEHRKNAJFb3Q==";
    /**
     * 公钥
     */
    public static String PUBLIC_KEY = "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDdB2wyzMp4htNaMZrj2zuMrhaBg8k1laWNlV+5Y4GNbqAMlkfczRRAGIZB50V3xNdUvxavQjVJMwGLVfPPOaLusRTwjb3h8Xpuh12CcvqExQLTnGI5CGe0563xBnUV+kmMku6KwFTpaqFEGe9C8yF/j29v02TXDxfH/8Zcxec/UwIBAw==";

    /**
     * 字符集
     */
    public static String CHARSET = "utf-8";

    /**
     * 签名算法
     */
    public static final String SIGNATURE_INSTANCE = "SHA1WithRSA";

    /**
     * 生成密钥对
     *
     * @param keyLength
     * @return KeyPair
     * @author : Yvon / 2021-11-10
     */
    public static KeyPair getKeyPair(int keyLength) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(keyLength);
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 公钥字符串转PublicKey实例
     *
     * @param publicKey
     * @return PublicKey
     * @author : Yvon / 2021-11-10
     */
    public static PublicKey getPublicKey(String publicKey) throws Exception {
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey.getBytes());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(keySpec);
    }

    /**
     * 私钥字符串转PrivateKey实例
     *
     * @param privateKey
     * @return PrivateKey
     * @author : Yvon / 2021-11-10
     */
    public static PrivateKey getPrivateKey(String privateKey) throws Exception {
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey.getBytes());
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * 公钥加密
     *
     * @param content 内容(字节)
     * @param publicKey 公钥
     * @return byte[]
     * @author : Yvon / 2021-11-10
     */
    public static byte[] encryptByPublicKey(byte[] content, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(content);
    }

    /**
     * 公钥加密
     *
     * @param content 内容(字节)
     * @return byte[]
     * @author : Yvon / 2021-11-10
     */
    public static byte[] encryptByPublicKey(byte[] content) throws Exception {
        return encryptByPublicKey(content, getPublicKey(PUBLIC_KEY));
    }

    /**
     * 公钥加密
     *
     * @param content   内容(字符)
     * @param publicKey 公钥字符
     * @return String
     * @author : Yvon / 2021-11-10
     */
    public static String encryptByPublicKey(String content, String publicKey) throws Exception {
        return new String(Base64.getEncoder().encode(encryptByPublicKey(content.getBytes(CHARSET), getPublicKey(publicKey))));

    }

    /**
     * 公钥加密
     *
     * @param content 内容(字符)
     * @return String
     * @author : Yvon / 2021-11-10
     */
    public static String encryptByPublicKey(String content) throws Exception {
        return new String(Base64.getEncoder().encode(encryptByPublicKey(content.getBytes(CHARSET))));
    }

    /**
     * 私钥解密
     *
     * @param content
     * @param privateKey
     * @return byte[]
     * @author : Yvon / 2021-11-10
     */
    public static byte[] decryptByPrivateKey(byte[] content, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(content);
    }

    /**
     * 私钥解密
     *
     * @param content 内容
     * @return byte[]
     * @author : Yvon / 2021-11-10
     */
    public static byte[] decryptByPrivateKey(byte[] content) throws Exception {
        return decryptByPrivateKey(content, getPrivateKey(PRIVATE_KEY));
    }

    /**
     * 私钥解密
     *
     * @param content    内容
     * @param privateKey 私钥
     * @return String
     * @author : Yvon / 2021-11-10
     */
    public static String decryptByPrivateKey(String content, String privateKey) throws Exception {
        return new String(decryptByPrivateKey(Base64.getDecoder().decode(content), getPrivateKey(privateKey)), CHARSET);

    }

    /**
     * 私钥解密
     *
     * @param content 内容
     * @return String
     * @author : Yvon / 2021-11-10
     */
    public static String decryptByPrivateKey(String content) throws Exception {
        return new String(decryptByPrivateKey(Base64.getDecoder().decode(content)), CHARSET);
    }

    /**
     * 私钥加密
     *
     * @param content
     * @param privateKey
     * @return byte[]
     * @author : Yvon / 2021-11-10
     */
    public static byte[] encryptByPrivateKey(byte[] content, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        return cipher.doFinal(content);
    }

    /**
     * 私钥加密
     *
     * @param content 内容
     * @return byte[]
     * @author : Yvon / 2021-11-10
     */
    public static byte[] encryptByPrivateKey(byte[] content) throws Exception {
        return encryptByPrivateKey(content, getPrivateKey(PRIVATE_KEY));
    }

    /**
     * 私钥加密
     *
     * @param content    内容
     * @param privateKey 私钥
     * @return String
     * @author : Yvon / 2021-11-10
     */
    public static String encryptByPrivateKey(String content, String privateKey) throws Exception {
        return new String(encryptByPrivateKey(content.getBytes(CHARSET), getPrivateKey(privateKey)), CHARSET);
    }

    /**
     * 私钥加密
     *
     * @param content 内容
     * @return String
     * @author : Yvon / 2021-11-10
     */
    public static String encryptByPrivateKey(String content) throws Exception {
        return new String(encryptByPrivateKey(content.getBytes(CHARSET)), CHARSET);
    }

    /**
     * 公钥解密
     * @param content
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey(byte[] content, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        return cipher.doFinal(content);
    }

    /**
     * 公钥解密
     *
     * @param content 内容
     * @return byte[]
     * @author : Yvon / 2021-11-10
     */
    public static byte[] decryptByPublicKey(byte[] content) throws Exception {
        return decryptByPublicKey(content, getPublicKey(PUBLIC_KEY));
    }

    /**
     * 公钥解密
     *
     * @param content   内容
     * @param publicKey 公钥
     * @return String
     * @author : Yvon / 2021-11-10
     */
    public static String decryptByPublicKey(String content, String publicKey) throws Exception {
        return new String(decryptByPublicKey(Base64.getDecoder().decode(content), getPublicKey(publicKey)), CHARSET);

    }

    /**
     * 公钥解密
     *
     * @param content 内容
     * @return String
     * @author : Yvon / 2021-11-10
     */
    public static String decryptByPublicKey(String content) throws Exception {
        return new String(decryptByPublicKey(Base64.getDecoder().decode(content)), CHARSET);
    }

    /**
     * 签名
     * @param content
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] sign(byte[] content, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance(SIGNATURE_INSTANCE);
        signature.initSign(privateKey);
        signature.update(content);
        return signature.sign();
    }

    /**
     * 签名
     *
     * @param content 内容
     * @return byte[]
     * @author : Yvon / 2021-11-10
     */
    public static byte[] sign(byte[] content) throws Exception {
        return sign(content, getPrivateKey(PRIVATE_KEY));
    }

    /**
     * 签名
     *
     * @param content    内容
     * @param privateKey 私钥
     * @return String
     * @author : Yvon / 2021-11-10
     */
    public static String sign(String content, String privateKey) throws Exception {
        return new String(Base64.getEncoder().encode(sign(content.getBytes(CHARSET), getPrivateKey(privateKey))), CHARSET);
    }

    /**
     * 签名
     *
     * @param content 内容
     * @return String
     * @author : Yvon / 2021-11-10
     */
    public static String sign(String content) throws Exception {
        return new String(Base64.getEncoder().encode(sign(content.getBytes(CHARSET))), CHARSET);
    }

    /**
     * 验签
     * @param content
     * @param sign
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static boolean verify(byte[] content, byte[] sign,  PublicKey publicKey) throws Exception {
        Signature signature = Signature.getInstance(SIGNATURE_INSTANCE);
        signature.initVerify(publicKey);
        signature.update(content);
        return signature.verify(sign);
    }

    /**
     * 验签
     *
     * @param content 内容
     * @param sign    标志
     * @return boolean
     * @author : Yvon / 2021-11-10
     */
    public static boolean verify(byte[] content, byte[] sign) throws Exception {
        return verify(content, sign, getPublicKey(PUBLIC_KEY));
    }

    /**
     * 验签
     *
     * @param content   内容
     * @param sign      签名
     * @param publicKey 公钥
     * @return boolean
     * @author : Yvon / 2021-11-10
     */
    public static boolean verify(String content, String sign, String publicKey) throws Exception {
        return verify(content.getBytes(CHARSET), Base64.getDecoder().decode(sign), getPublicKey(publicKey));
    }

    /**
     * 验签
     *
     * @param content 内容
     * @param sign    签名
     * @return boolean
     * @author : Yvon / 2021-11-10
     */
    public static boolean verify(String content, String sign) throws Exception {
        return verify(content.getBytes(CHARSET), Base64.getDecoder().decode(sign), getPublicKey(PUBLIC_KEY));
    }
}

